package qc.module.platform.api.controller;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import qc.common.core.constants.QCAuthConstant;
import qc.common.core.exception.QCPromptException;
import qc.common.core.exception.QcTokenInvalidException;
import qc.common.core.tree.QCTreeNode;
import qc.common.core.unify.QCUnifyReturnValue;
import qc.module.platform.dto.param.group.ParamGroupDto;
import qc.module.platform.dto.param.value.ObjectParamValuesDto;
import qc.module.platform.dto.param.value.ParamValuesGetConditionDto;
import qc.module.platform.dto.project.*;
import qc.module.platform.dto.user.UserQueryConditionDto;
import qc.module.platform.dto.user.UserSimpleInfoDto;
import qc.module.platform.entity.QcDeptUser;
import qc.module.platform.entity.QcDepts;
import qc.module.platform.entity.QcUserloginLogs;
import qc.module.platform.entity.QcUsers;
import qc.module.platform.service.*;

import javax.servlet.http.HttpServletRequest;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * ProjectController
 *
 * @author QuCheng Tech
 * @create 2023/1/9
 */
@RestController
@RequestMapping("/project")
public class ProjectController {
    private ProjectService projectService;
    private UserProjectService userProjectService;
    private UserService userService;
    private ParamService paramService;
    private ParamValueService paramValueService;
    
    @Autowired
    private DeptService deptService;
    @Autowired
    private DeptUserService deptUserService;

    @Autowired
    private UserLoginLogService userLoginLogService;

    @Autowired
    HttpServletRequest request;

    @Autowired
    public void setProjectService(ProjectService projectService) {
        this.projectService = projectService;
    }

    @Autowired
    public void setUserProjectService(UserProjectService userProjectService) {
        this.userProjectService = userProjectService;
    }

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @Autowired
    public void setParamService(ParamService paramService) {
        this.paramService = paramService;
    }

    @Autowired
    public void setParamValueService(ParamValueService paramValueService) {
        this.paramValueService = paramValueService;
    }

    //是否为逻辑删除，为true表示逻辑删除--修改记录标记，为false表示物理删除--从数据库表中删除记录
    private static final boolean isLogicDelete = false;

    /**
     * 新增项目
     *
     * @param dto 项目
     * @return 成功返回null
     * @author QuCheng Tech
     * @since 2023/6/26
     */
    @RequestMapping(value = "/add", method = {RequestMethod.POST})
    public String add(@RequestBody ProjectDto dto) {
        return projectService.add(dto);
    }

    /**
     * 修改项目
     *
     * @param dto 项目
     * @return 成功返回null
     * @author QuCheng Tech
     * @since 2023/6/26
     */
    @RequestMapping(value = "/update", method = {RequestMethod.PUT, RequestMethod.POST})
    public String update(@RequestBody ProjectDto dto) {
        return projectService.update(dto);
    }

    /**
     * 删除项目，物理删除
     *
     * @param id 项目编码
     * @return 成功返回null
     * @author QuCheng Tech
     * @since 2023/6/27
     */
    @RequestMapping(value = "/delete", method = {RequestMethod.DELETE})
    public String deleteByParam(@RequestParam String id) {
        return projectService.delete(id, isLogicDelete);
    }

    /**
     * 删除项目，物理删除
     *
     * @param id 项目编码
     * @return 成功返回null
     * @author QuCheng Tech
     * @since 2023/6/27
     */
    @RequestMapping(value = "/delete/{id}", method = {RequestMethod.DELETE})
    public String deleteByPath(@PathVariable String id) {
        return projectService.delete(id, isLogicDelete);
    }

    /**
     * 获取指定项目信息，不对项目状态进行判断
     *
     * @param id 项目编码
     * @return 项目信息
     * @author QuCheng Tech
     * @since 2023/6/27
     */
    @RequestMapping(value = "/get", method = {RequestMethod.GET})
    public ProjectDto getByParam(@RequestParam String id) throws QCPromptException {
        return projectService.get(id);
    }

    /**
     * 获取指定项目信息，不对项目状态进行判断
     *
     * @param id 项目编码
     * @return 项目信息
     * @author QuCheng Tech
     * @since 2023/6/27
     */
    @RequestMapping(value = "/get/{id}", method = {RequestMethod.GET})
    public ProjectDto getByPath(@PathVariable String id) throws QCPromptException {
        return projectService.get(id);
    }

    /**
     * 根据关键字查询，关键字可以为项目编码、项目名称、项目标题(完整、简要标题)，没有则查询全部
     *
     * @param dto ProjectQueryConditionDto
     * @return 项目信息集合
     * @author QuCheng Tech
     * @since 2023/2/8
     */
    @RequestMapping(value = "/query", method = {RequestMethod.GET, RequestMethod.POST})
    public List<ProjectDto> query(@RequestBody ProjectQueryConditionDto dto) {
        return projectService.query(dto, false);
    }

    /**
     * 根据项目编码获取关联的用户简要信息集合
     *
     * @param id 项目编码
     * @return 关联用户简单信息列表
     * @author QuCheng Tech
     * @since 2023/6/27
     */
    @RequestMapping(value = "/getusers", method = {RequestMethod.GET})
    public List<UserSimpleInfoDto> getProjectUsersByParam(@RequestParam String id) throws QCPromptException {
        UserQueryConditionDto condition = new UserQueryConditionDto();
        condition.setProject(id);

        return userService.queryProjectUserSimple(condition);
    }

    /**
     * 获取项目关联用户
     *
     * @param id 项目编码
     * @return 关联用户简单信息列表
     * @author QuCheng Tech
     * @since 2023/6/27
     */
    @RequestMapping(value = "/getusers/{id}", method = {RequestMethod.GET})
    public List<UserSimpleInfoDto> getProjectUsersByPath(@PathVariable String id) throws QCPromptException {
        UserQueryConditionDto condition = new UserQueryConditionDto();
        condition.setProject(id);

        return userService.queryProjectUserSimple(condition);
    }

    /**
     * 添加项目关联用户，可关联多个用户
     *
     * @param dto 项目关联用户信息
     * @return 成功返回null
     * @author QuCheng Tech
     * @since 2023/6/27
     */
    @RequestMapping(value = "/addusers", method = {RequestMethod.POST})
    public String addProjectUsers(@RequestBody ProjectUserRelateDto dto) {
        if (dto == null)
            return QCUnifyReturnValue.Warn("设置信息不能为空");

        String projectCode = dto.getProject();
        int[] userIds = dto.getUids();

        if (StringUtils.isBlank(projectCode))
            return QCUnifyReturnValue.Warn("设置的项目编码不能为空");
        if (userIds == null || userIds.length < 0x1)
            return QCUnifyReturnValue.Warn("设置的用户信息不能为空");

        if (!projectService.hasCodeExist(projectCode))
            return QCUnifyReturnValue.Warn("设置的项目编码不存在");

        userProjectService.add(projectCode, userIds);

        return QCUnifyReturnValue.Success();
    }

    /**
     * 删除项目指定用户关联关系，可选择多个用户
     *
     * @param dto 项目关联用户信息
     * @return 成功返回null
     * @author QuCheng Tech
     * @since 2023/6/27
     */
    @RequestMapping(value = "/deleteusers", method = {RequestMethod.DELETE})
    public String deleteProjectUsers(@RequestBody ProjectUserRelateDto dto) {
        if (dto == null)
            return QCUnifyReturnValue.Warn("设置信息不能为空");

        String projectCode = dto.getProject();
        int[] userIds = dto.getUids();

        if (StringUtils.isBlank(projectCode))
            return QCUnifyReturnValue.Warn("设置的项目编码不能为空");
        if (userIds == null || userIds.length < 0x1)
            return QCUnifyReturnValue.Warn("设置的用户信息不能为空");

        if (!projectService.hasCodeExist(projectCode))
            return QCUnifyReturnValue.Warn("设置的项目编码不存在");

        userProjectService.delete(projectCode, userIds);

        return QCUnifyReturnValue.Success();
    }

    /**
     * 根据指定的项目编码和参数分组编码获取参数值信息
     *
     * @param condition 指定的项目编码和参数分组编码
     * @return qc.module.platform.dto.param.value.ObjectParamValuesDto
     * @author QuCheng Tech
     * @since 2024/3/4
     */
    @RequestMapping(value = "/paramvalue", method = {RequestMethod.GET, RequestMethod.POST})
    public ObjectParamValuesDto getParamValue(@RequestBody ProjectParamValueConditionDto condition) throws QCPromptException, SQLException, QcTokenInvalidException {
        //判断输入信息和条件
        if (condition == null)
            throw new QCPromptException("获取项目参数信息的条件对象不能为空");
        //项目编码：如果传入中为空，依次从header、根据token获取
        if (StringUtils.isBlank(condition.getProjectcode())) {
            //从headers中获取项目编码
            String projectCode = request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY);
            if (StringUtils.isNotBlank(projectCode)) {
                condition.setProjectcode(projectCode);
            } else {
                //如果header中的项目编码为空，根据token获取项目编码
                String token = request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY);
                if (StringUtils.isNotBlank(token)) {
                    //从uac中根据token获取项目编码
                    QcUserloginLogs loginLog = userLoginLogService.getUserLoginLogByToken(token, true);
                    if (loginLog != null && StringUtils.isNotBlank(loginLog.getProject()))
                        condition.setProjectcode(loginLog.getProject());
                }
            }
        }
        if (StringUtils.isBlank(condition.getProjectcode()))
            throw new QCPromptException("获取项目参数信息的项目编码不能为空");

        ParamValuesGetConditionDto getParamValuesCondition = new ParamValuesGetConditionDto();
        //先默认查询项目参数对应的表名为：qc_project
        getParamValuesCondition.setTablecode("qc_project");
        getParamValuesCondition.setObjectids(condition.getProjectcode());
        //查询参数值的节点名称：如果在传入条件中直接指定节点名称则直接使用，如果没有指定则根据分组编码进行获取
        if (StringUtils.isNotBlank(condition.getParamnodes())) {
            getParamValuesCondition.setParamnodes(condition.getParamnodes());
        } else {
            if (StringUtils.isBlank(condition.getGroupcode()))
                throw new QCPromptException("获取项目参数信息的参数分组编码不能为空");

            //从传入的参数分组编码获取参数分组信息，使用参数分组信息中的数据库表编码和节点名称
            ParamGroupDto paramGroup = paramService.getGroup(condition.getGroupcode());
            if (paramGroup == null)
                throw new QCPromptException("获取项目参数信息的参数分组编码获取不到有效的参数分组信息");

            getParamValuesCondition.setTablecode(paramGroup.getTablecode());
            getParamValuesCondition.setParamnodes(paramGroup.getNodes());
        }

        List<ObjectParamValuesDto> paramValues = paramValueService.getValues(getParamValuesCondition);
        //查询指定的1个项目的参数值，因此集合中应该至多有1个，返回结果为参数值集合中的第1个
        if (paramValues != null && paramValues.size() > 0x0)
            return paramValues.get(0x0);

        return null;
    }

    /**
     * 获取项目中的部门和用户Tree
     * 可以用于查询任务协同中获取上报、委派、指派等操作时的选择部门和用户数据来源；在返回数据的tree节点中使用type标识节点是部门还是用户；
     *
     * @param condition
     * @return List<QCTreeNode>
     * @author QuCheng Tech
     * @since 2024/9/19
     */
    @RequestMapping(value = "/deptusertree", method = {RequestMethod.GET, RequestMethod.POST})
    public List<QCTreeNode> getProjectDeptUserTree(@RequestBody ProjectGetDeptAndUserConditionDto condition)
            throws QCPromptException, QcTokenInvalidException {
        //根据token获取当前用户信息
        String token = request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY);
        QcUserloginLogs loginLog = userLoginLogService.getUserLoginLogByToken(token, true);
        int userId = loginLog.getUid().intValue();

        //查询条件验证
        if (StringUtils.isBlank(condition.getProject())) throw new QCPromptException("项目编码不能为空");

        //判断查询条件中不包含的层级，默认包含
        //层级分为上级-1、同级-2、下级-4，可以指定不包含的层级；如委派工作只能对下级，不包含的层级为上级+同级=3
        boolean isIncludeSuperLevel = true;//是否包含上级
        boolean isIncludeSameLevel = true;//是否包含同级
        boolean isIncludeSubLevel = true;//是否包含下级
        if (condition.getExcludelevel() != null) {
            if ((condition.getExcludelevel() & 0x1) == 0x1) isIncludeSuperLevel = false;
            if ((condition.getExcludelevel() & 0x2) == 0x2) isIncludeSameLevel = false;
            if ((condition.getExcludelevel() & 0x4) == 0x4) isIncludeSubLevel = false;
        }

        // 根据项目编码获取项目部门集合
        List<QcDepts> projectAllDepts = deptService.getProjectAllDepts(condition.getProject(), false);
        if (projectAllDepts == null || projectAllDepts.isEmpty()) return null;

        //查询所有项目用户集合
        UserQueryConditionDto conditionDto = new UserQueryConditionDto();
        conditionDto.setProject(condition.getProject());
        List<QcUsers> projectUsers = userService.queryProjectUsersList(conditionDto);

        // 通过项目部门id查询部门和用户的关联关系
        List<Integer> projectDeptsIds = projectAllDepts.stream().map(QcDepts::getId).collect(Collectors.toList());
        List<QcDeptUser> deptUserRelations = deptUserService.getEntityByDeptIds(projectDeptsIds);
        // 获取关联部门的用户ID集合
        List<Integer> userIdsInDept = deptUserRelations.stream()
                .map(QcDeptUser::getUserid).distinct().collect(Collectors.toList());
        
        //根据当前用户ID查找当前用户所在部门，如果有多个部门，默认为层级最高的部门
        List<QcDeptUser> currentDeptUserReletions = deptUserRelations.stream()
                .filter(deptUserRelation -> deptUserRelation.getUserid().equals(userId)).collect(Collectors.toList());
        QcDepts dept;//当前用户所在部门
        if (currentDeptUserReletions != null && currentDeptUserReletions.size() > 0x0){
            if (currentDeptUserReletions.size() <= 0x1){
                //只有一个部门
                dept = projectAllDepts.stream().filter(d -> d.getId().equals(currentDeptUserReletions.get(0x0)
                        .getDeptid())).findAny().orElse(null);
            }else {
                //有多个部门，找出层级最高的部门为用户所在部门
                List<Integer> detpIds = currentDeptUserReletions.stream()
                        .map(QcDeptUser::getDeptid).collect(Collectors.toList());
                List<QcDepts> depts = projectAllDepts.stream().filter(d -> 
                        detpIds.contains(d.getId())).collect(Collectors.toList());
                //查找depts中是否有根部门，如果有则设置为当前用户所在部门
                List<QcDepts> rootDepts = depts.stream().filter(d -> d != null && (d.getParentid() == null 
                        || d.getParentid() == 0x0)).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(rootDepts)){
                    dept = rootDepts.get(0x0);
                }else {
                    //TODO 没有根部门，如何知道所在的部门哪个层级最高？？暂取第一个部门
                    dept = depts.get(0x0);
                }
            }
        } else {
            dept = null;
        }
        if (dept == null) throw new QCPromptException("当前用户无有效部门");
        
        
        //根据不包含的层级，找出需要移除的部门和用户
        List<Integer> removeDeptIds = new ArrayList<>();//需要移除的部门ID集合
        List<Integer> removeUserIds = new ArrayList<>();//需要移除的用户ID集合
        //如果不包含上级，分为两种情况：当前用户是否为部门负责人处理：
        // 如果是部门负责人，则上级为当前用户所在部门的所有上级部门和用户；
        // 如果不是部门负责人，上级为当前用户所在部门及部门负责人，以及所有上级部门和用户
        QcDeptUser deptUser = currentDeptUserReletions.stream().filter(d -> d.getDeptid()
                .equals(dept.getId())).findAny().orElse(null);
        if (!isIncludeSuperLevel){
            //判断当前用户所在部门是否为部门负责人
            if (deptUser.getIsleader() != null && deptUser.getIsleader()){
                //是部门负责人，找出当前用户所在部门的所有上级部门和上级部门的用户
                getParentDeptIds(projectAllDepts,dept.getParentid(),removeDeptIds);
                //根据不包含的部门ID，找出这些部门的用户ID
                if (CollectionUtils.isNotEmpty(removeDeptIds)){
                    removeUserIds = deptUserRelations.stream().filter(relation ->
                                    removeDeptIds.contains(relation.getDeptid()))
                            .map(QcDeptUser::getUserid).distinct().collect(Collectors.toList()); 
                }
            }else{
                //不是部门负责人，包含当前所在部门
                getParentDeptIds(projectAllDepts,dept.getParentid(),removeDeptIds);
                removeDeptIds.add(dept.getId());
                //根据不包含的部门ID，找出这些部门的用户ID
                if (CollectionUtils.isNotEmpty(removeDeptIds)){
                    removeUserIds = deptUserRelations.stream().filter(relation ->
                                    removeDeptIds.contains(relation.getDeptid()))
                            .map(QcDeptUser::getUserid).distinct().collect(Collectors.toList());
                }
            }
        }
        
        //如果不包含同级，分为两种情况：当前用户是否为部门负责人处理：
        //如果是部门负责人，则同级为当前用户所在部门的上级部门下的其他部门和用户；
        //如果不是部门负责人，则同级为当前用户所在部门下的其它用户（不包含部门负责人）
        if (!isIncludeSameLevel){
            //判断当前用户所在部门是否为部门负责人
            if (deptUser.getIsleader() != null && deptUser.getIsleader()){
                //是部门负责人
                if (dept.getParentid() != null && dept.getParentid() != 0x0){
                    List<QcDepts> sameLevelDepts = projectAllDepts.stream().filter(d -> dept.getParentid().equals(d.getParentid()))
                            .collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(sameLevelDepts)){
                        List<Integer> sameLevelDeptIds = sameLevelDepts.stream().map(QcDepts::getId).collect(Collectors.toList());
                        removeDeptIds.addAll(sameLevelDeptIds);
                        removeDeptIds.remove(dept.getId());
                        //根据不包含的部门ID，找出这些部门的用户ID
                        if (CollectionUtils.isNotEmpty(removeDeptIds)){
                            removeUserIds = deptUserRelations.stream().filter(relation ->
                                            removeDeptIds.contains(relation.getDeptid()))
                                    .map(QcDeptUser::getUserid).distinct().collect(Collectors.toList());
                        }
                    }
                    
                }else {
                    //找出所有根部门，不包含当前所在部门
                    List<QcDepts> sameLevelDepts = projectAllDepts.stream().filter(d -> d.getParentid() == null || d.getParentid() == 0x0)
                            .collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(sameLevelDepts)){
                        List<Integer> sameLevelDeptIds = sameLevelDepts.stream().map(QcDepts::getId).collect(Collectors.toList());
                        removeDeptIds.addAll(sameLevelDeptIds);
                        removeDeptIds.remove(dept.getId());
                        //根据不包含的部门ID，找出这些部门的用户ID
                        if (CollectionUtils.isNotEmpty(removeDeptIds)){
                            removeUserIds = deptUserRelations.stream().filter(relation ->
                                            removeDeptIds.contains(relation.getDeptid()))
                                    .map(QcDeptUser::getUserid).distinct().collect(Collectors.toList());
                        }
                    }
                }
            }else{
                //不是部门负责人
                //找出当前用户部门下的所有用户，把普通用户ID添加到用户移除列表中
                List<QcDeptUser> deptUsers = deptUserRelations.stream().filter(relation -> 
                        relation.getDeptid().equals(dept.getId())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(deptUsers)){
                    removeUserIds = deptUsers.stream().filter(relation -> relation.getIsleader().equals(false))
                            .map(QcDeptUser::getUserid).distinct().collect(Collectors.toList());
                }
            }
        }
        
        //如果不包含下级，分为两种情况：当前用户是否为部门负责人处理：
        //如果是部门负责人，则下级为当前用户所在部门的其它用户和所有子孙级部门和用户；
        //如果不是部门负责人
        if (!isIncludeSubLevel){
            //判断当前用户所在部门是否为部门负责人
            if (deptUser.getIsleader() != null && deptUser.getIsleader()){
                //是部门负责人
                //找出当前用户所在部门的所有下级部门
                List<Integer> parentDeptIds = new ArrayList<>();
                parentDeptIds.add(dept.getId());
                getSubDeptIds(projectAllDepts,parentDeptIds,removeDeptIds);
                //根据不包含的部门ID，找出这些部门的用户ID
                if (CollectionUtils.isNotEmpty(removeDeptIds)){
                    removeUserIds = deptUserRelations.stream().filter(relation ->
                                    removeDeptIds.contains(relation.getDeptid()))
                            .map(QcDeptUser::getUserid).distinct().collect(Collectors.toList());
                }
                //找出当前用户所在部门下的其它普通用户
                List<Integer> currentDeptUserIds = deptUserRelations.stream().filter(relation -> 
                        relation.getDeptid().equals(dept.getId()) && relation.getIsleader().equals(false))
                        .map(QcDeptUser::getUserid).distinct().collect(Collectors.toList());
                removeUserIds.addAll(currentDeptUserIds);
            }else{
                //TODO 不是部门负责人
                
            }
        }

        //判断查询条件中的是否包含当前用户，如果不包含，将当前用户从用户ID集合中移除
        if (condition.getExcludeself()) {
            if (!removeUserIds.contains(userId))
                removeUserIds.add(userId);
        }
        
        //根据需要移除的部门ID和用户ID，分别从所有部门中和所有部门用户中筛选出需要返回的部门和用户ID
        List<QcDepts> resultDepts = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(removeDeptIds)){
            List<Integer> allDeptIds = projectAllDepts.stream().map(QcDepts::getId).collect(Collectors.toList());
            allDeptIds.removeAll(removeDeptIds);
            resultDepts = projectAllDepts.stream().filter(d -> allDeptIds.contains(d.getId())).collect(Collectors.toList());
        }else {
            resultDepts = projectAllDepts;
        }
        if (CollectionUtils.isNotEmpty(removeUserIds)) 
            userIdsInDept.removeAll(removeUserIds);
        
        //将最后剩余的部门构建为返回对象结构
        //找出根部门集合
        List<QcDepts> rootDepts = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(resultDepts)){
            for (QcDepts qcDept : resultDepts){
                getRootDept(resultDepts,qcDept,rootDepts);
            }
        }

        //构建返回对象集合
        List<QCTreeNode> result = new ArrayList<>();
        List<QcDepts> level1Depts = rootDepts.stream().distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(level1Depts)){
            for (QcDepts level1Dept : level1Depts){
                QCTreeNode level1DeptNode = new QCTreeNode();
                level1DeptNode.setKey(level1Dept.getId().toString());
                level1DeptNode.setTitle(level1Dept.getName());
                level1DeptNode.setLeaf(true);
                level1DeptNode.setType("1");//数据类型为部门
                List<QCTreeNode> level1Children = new ArrayList<>();
                
                //获取下级部门
                List<QcDepts> level2Depts = resultDepts.stream().filter(d -> d.getParentid() != null && 
                        d.getParentid().equals(level1Dept.getId())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(level2Depts)){
                    level1DeptNode.setLeaf(false);
                    for (QcDepts level2Dept : level2Depts){
                        QCTreeNode level2DeptNode = new QCTreeNode();
                        level2DeptNode.setKey(level2Dept.getId().toString());
                        level2DeptNode.setTitle(level2Dept.getName());
                        level2DeptNode.setLeaf(true);
                        level2DeptNode.setType("1");//数据类型为部门
                        level2DeptNode.setPid(level1DeptNode.key);
                        List<QCTreeNode> level2Children = new ArrayList<>();
                        
                        //获取下级部门
                        List<QcDepts> level3Depts = resultDepts.stream().filter(d -> d.getParentid() != null && 
                                d.getParentid().equals(level2Dept.getId())).collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(level3Depts)){
                            level2DeptNode.setLeaf(false);
                            for (QcDepts level3Dept : level3Depts){
                                QCTreeNode level3DeptNode = new QCTreeNode();
                                level3DeptNode.setKey(level3Dept.getId().toString());
                                level3DeptNode.setTitle(level3Dept.getName());
                                level3DeptNode.setLeaf(true);
                                level3DeptNode.setType("1");//数据类型为部门
                                level3DeptNode.setPid(level2DeptNode.key);
                                List<QCTreeNode> level3Children = new ArrayList<>();
                                //TODO 继续获取下级部门

                                //添加三级部门用户：找出部门管理的用户ID集合，如果有则将用户查找设置到一级部门的子级中
                                List<Integer> level3AllUserIds = deptUserRelations.stream().filter(relation ->
                                                level3Dept.getId().equals(relation.getDeptid()))
                                        .map(QcDeptUser::getUserid).collect(Collectors.toList());
                                List<Integer> level3UserIds = level3AllUserIds.stream().filter(uid -> userIdsInDept.contains(uid))
                                        .distinct().collect(Collectors.toList());
                                //获得当前部门关联的用户集合
                                List<QcUsers> dept3Users = projectUsers.stream()
                                        .filter(user -> level3UserIds.contains(user.getId()))
                                        .collect(Collectors.toList());
                                if (CollectionUtils.isNotEmpty(dept3Users)){
                                    level3DeptNode.setLeaf(false);
                                    for (QcUsers level3User : dept3Users){
                                        QCTreeNode level3UserNode = new QCTreeNode();
                                        level3UserNode.setKey(level3User.getId().toString());
                                        level3UserNode.setTitle(level3User.getName());
                                        level3UserNode.setLeaf(true);
                                        level3UserNode.setType("2");
                                        level3DeptNode.setPid(level2DeptNode.key);
                                        level3Children.add(level3UserNode);
                                    }
                                }
                                level3DeptNode.setChildren(level3Children);
                                level2Children.add(level3DeptNode);
                            }
                        }
                        //添加二级部门用户：找出部门管理的用户ID集合，如果有则将用户查找设置到一级部门的子级中
                        List<Integer> level2AllUserIds = deptUserRelations.stream().filter(relation ->
                                        level2Dept.getId().equals(relation.getDeptid()))
                                .map(QcDeptUser::getUserid).collect(Collectors.toList());
                        List<Integer> level2UserIds = level2AllUserIds.stream().filter(uid -> userIdsInDept.contains(uid))
                                .distinct().collect(Collectors.toList());
                        //获得当前部门关联的用户集合
                        List<QcUsers> dept2Users = projectUsers.stream()
                                .filter(user -> level2UserIds.contains(user.getId()))
                                .collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(dept2Users)){
                            level2DeptNode.setLeaf(false);
                            for (QcUsers level2User : dept2Users){
                                QCTreeNode level2UserNode = new QCTreeNode();
                                level2UserNode.setKey(level2User.getId().toString());
                                level2UserNode.setTitle(level2User.getName());
                                level2UserNode.setLeaf(true);
                                level2UserNode.setType("2");
                                level2DeptNode.setPid(level1DeptNode.key);
                                level2Children.add(level2UserNode);
                            }
                        }
                        level2DeptNode.setChildren(level2Children);
                        level1Children.add(level2DeptNode);
                    }
                }
                //添加一级部门用户：找出部门管理的用户ID集合，如果有则将用户查找设置到一级部门的子级中
                List<Integer> level1AllUserIds = deptUserRelations.stream().filter(relation ->
                                level1Dept.getId().equals(relation.getDeptid()))
                        .map(QcDeptUser::getUserid).collect(Collectors.toList());
                List<Integer> level1UserIds = level1AllUserIds.stream().filter(uid -> userIdsInDept.contains(uid))
                        .distinct().collect(Collectors.toList());
                //获得当前部门关联的用户集合
                List<QcUsers> dep1tUsers = projectUsers.stream()
                        .filter(user -> level1UserIds.contains(user.getId()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(dep1tUsers)){
                    level1DeptNode.setLeaf(false);
                    for (QcUsers level1User : dep1tUsers){
                        QCTreeNode level1UserNode = new QCTreeNode();
                        level1UserNode.setKey(level1User.getId().toString());
                        level1UserNode.setTitle(level1User.getName());
                        level1UserNode.setLeaf(true);
                        level1UserNode.setType("2");
                        level1Children.add(level1UserNode);
                    }
                }
                level1DeptNode.setChildren(level1Children);
                result.add(level1DeptNode);
            }
        }

        return result;
    }

    /**
     * 设置指定项目的参数
     *
     * @param dto 项目编码和参数信息
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/2/3
     */
    @RequestMapping(value = "/params", method = {RequestMethod.PUT, RequestMethod.POST})
    public String setParams(@RequestBody ProjectDto dto) {
        if (dto == null)
            return QCUnifyReturnValue.Warn("要修改参数的信息为空");
        if (StringUtils.isBlank(dto.getCode()))
            return QCUnifyReturnValue.Warn("要修改参数的项目编码不能为空");
        if (projectService.hasCodeExist(dto.getCode()) == false)
            return QCUnifyReturnValue.Warn("要修改参数的项目信息不存在");

        return projectService.setParams(dto.getCode(), dto.getParams());
    }

    /**
     * 查找根部门
     *
     * @param resultDepts 所有部门
     * @param qcDept      当前部门
     * @param rootDepts   返回的根部门集合
     */
    private void getRootDept(List<QcDepts> resultDepts, QcDepts qcDept, List<QcDepts> rootDepts) {
        if (qcDept.getParentid() == null || qcDept.getParentid() == 0x0) {
            //如果部门是根部门，直接加到根部门集合中
            rootDepts.add(qcDept);
        } else {
            //如果不是根部门，根据部门的上级部门ID查找是否有上级部门，如果有上级部门再继续找上级部门的上级，直到找不到为止；
            // 如果没有则将当前部门加到根部门中
            QcDepts parentDept = resultDepts.stream().filter(d -> d.getId().equals(qcDept.getParentid())).findAny().orElse(null);
            if (Objects.nonNull(parentDept)) {
                getRootDept(resultDepts, parentDept, rootDepts);
            } else {
                rootDepts.add(qcDept);
            }
        }
    }
    
    /**
     * 根据父部门id递归向上查找上级部门ID
     * 
     * @param projectAllDepts 所有项目部门集合
     * @param parentId 上级部门ID
     * @param deptIds 返回的部门ID集合
     */
    public void getParentDeptIds(List<QcDepts> projectAllDepts,Integer parentId,List<Integer> deptIds){
        if (parentId != null && parentId != 0x0){
            for (QcDepts dept : projectAllDepts){
                if (parentId.equals(dept.getId())) {
                    getParentDeptIds(projectAllDepts,dept.getParentid(),deptIds);
                    deptIds.add(parentId);
                }
            }
        }
    }

    /**
     * 根据父级部门递归向下查找子级部门ID
     * @param projectAllDepts 所有项目部门集合
     * @param parentDeptIds 父级部门ID信息
     * @param deptIds 返回的部门ID集合
     */
    public void getSubDeptIds(List<QcDepts> projectAllDepts,List<Integer> parentDeptIds,List<Integer> deptIds){
        if (CollectionUtils.isNotEmpty(parentDeptIds)){
            for (Integer deptId : parentDeptIds){
                //获取子级部门信息集合
                List<QcDepts> subDepts = projectAllDepts.stream().filter(p -> deptId.equals(p.getParentid()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(subDepts)){
                    getSubDeptIds(projectAllDepts,subDepts.stream().map(QcDepts::getId).collect(Collectors.toList()), deptIds);
                    List<Integer> subDeptIds = subDepts.stream().map(QcDepts::getId).collect(Collectors.toList());
                    deptIds.addAll(subDeptIds);
                }
            }
        }
    }
}
